<script setup lang="ts">
import type { AxiosRequestConfig } from 'axios'
import type {
  BusinessUIAction,
  BusinessUIFile,
  BusinessUIFormType,
  BusinessUIQueryColumnType,
  BusinessUITableType,
  DicType,
  WorkflowDesignRow
} from '@/types/custom'
import { ElMessage } from 'element-plus'
import { computed, nextTick, onBeforeMount, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { approvalStatusList, formatColumnRows } from '@/utils/custom'
import { assign, clone } from 'xe-utils'
import { useBaseApi, useBaseFileApi } from '@/api/base'
import { isObject } from '@vueuse/core'
import {
  getLinkageParams,
  onComponentServerFetch,
  onFetchIns,
  onFetchUser,
  onInitApiData,
  setFormDefaultParams,
  type StateInterface
} from '@/views/components/form/libs'
import emitter from '@/utils/mitt'

import TemplateFormBox from '@/views/components/form/components/TemplateFormBox.vue'
import TemplateFormDetail from '@/views/components/form/components/TemplateFormDetail.vue'

interface Props {
  dicTable?: DicType[]
  wfDesign?: WorkflowDesignRow
  uiForm?: BusinessUIFormType
  uiTable?: BusinessUITableType
  uiActions?: BusinessUIAction[]
  can_edit_items?: string[]
  isForm?: boolean
  labelPosition?: string
  params?: TypedAny
}

interface FormParamsType {
  [key: string]: any

  files?: BusinessUIFile[]
}

/**
 * 更新表单
 */
interface UpdateParentType {
  id: string
  forms: {
    id: string
    update: TypedAny
  }[]
}

// 当前表的id
const modelValue = defineModel()

const props = defineProps<Props>()

// 基础接口
const { UploadBaseFile, UploadBaseImage } = useBaseFileApi()
const { CustomRequest, GetTypeDictionary } = useBaseApi()

// 表格title布局
const formLabelPosition = ref(props.labelPosition || 'top')
// 加载中
const loading = ref(false)
// 表单
const ruleFormRef = ref<InstanceType<typeof TemplateFormBox>>()
// 表单数据
const formParams = ref<FormParamsType>({})
// 格式化后的表单数据
const formatParams = ref<FormParamsType>({})
// 部门-用户
const userItems = ref<SelectOptionType[]>([])
// 流程图列表
const insItems = ref<SelectOptionType[]>([])
// 所有字典
const dicItems = ref<DicType[]>([])
// 动态数据
const state = reactive<StateInterface>({})
// 初始值
const objectEqual = ref<TypedAny>({})
// 请求参数
const config: AxiosRequestConfig = {
  url: '/test',
  method: 'POST',
  data: {}
}

// 默认参数
const default_value_parse = computed(() => {
  return props.uiForm?.default_value_parse || {}
})

// 全部表单列
const uiFormItems = computed(() => props.uiForm?.items || [])

// 过滤后表单列
const formItems = computed(() => uiFormItems.value.filter((f) => !isRadioButton(f)))

/**
 * 是否是分组
 * @param form
 */
const isRadioButton = (form: BusinessUIQueryColumnType) => {
  return ['el-radio-button'].includes(form.component)
}

/**
 * 是否联动
 * @param form
 */
const onLinkageChange = (form: BusinessUIQueryColumnType) => {
  if (form.linkage) {
    const linkage = form.set_json_parse.linkage || []
    const list = uiFormItems.value.filter((f) => linkage.includes(f.field))
    onInitDefaultData(list)
  }
}

/**
 * 获取选择器下拉
 * @param form
 */
const getOptions = (form: BusinessUIQueryColumnType): SelectOptionType[] => {
  if (form.component === 'sys-ins') {
    return insItems.value
  } else if (form.component === 'sys-wf-status') {
    return approvalStatusList
  } else if (form.component === 'sys-user') {
    return userItems.value
  } else if (
    [
      'el-select',
      'el-checkbox-group',
      'el-radio-group',
      'el-radio-button',
      'el-segmented'
    ].includes(form.component)
  ) {
    return getDicOptions(form)
  } else if (form.options) {
    return form.options
  } else if (['api-select', 'api-tree-select'].includes(form.component)) {
    return state[form.field] || []
  } else {
    return state[form.component] || []
  }
}

/**
 * 获取字典下拉
 * @param form
 */
const getDicOptions = (form: BusinessUIQueryColumnType) => {
  const list: SelectOptionType[] = []
  dicItems.value
    .filter((f) => f.column_name === form.field)
    .forEach((v) => {
      list.push({
        value: ['el-segmented'].includes(form.component) ? Number(v.value_text) : v.value_text,
        label: v.display_text
      })
    })
  return list
}

/**
 * 获取所有字典
 */
const onFetchDictionary = async () => {
  if (props.uiForm?.type_name && !props.dicTable) {
    const { data } = await GetTypeDictionary({ type_name: props.uiForm.type_name })
    dicItems.value = data
  } else {
    dicItems.value = props.dicTable || []
  }
}

/**
 * 表单默认下拉
 * @param list
 */
const onInitDefaultData = (list: BusinessUIQueryColumnType[]) => {
  const params = getLinkageParams(unref(uiFormItems), unref(formParams))
  if (list.some((s) => ['sys-user'].includes(s.component))) {
    onFetchUser(list, params).then((data) => {
      userItems.value = data
    })
  }
  if (list.some((s) => ['sys-ins'].includes(s.component))) {
    onFetchIns(list, params).then((data) => {
      insItems.value = data
    })
  }
  onComponentServerFetch(list, state, params, unref(formParams))
  onInitApiData(list, state, params, unref(formParams))
}

/**
 * 重置
 */
const onResetParams = () => {
  const params = assign(setFormDefaultParams(unref(uiFormItems), {}), unref(default_value_parse))
  objectEqual.value = clone(params, true)
  formParams.value = params
}

const onFetch = async () => {
  loading.value = true
  try {
    if (!props.uiForm?.api) return ElMessage.warning('未配置表单接口')

    if (modelValue.value) {
      const { data } = await CustomRequest<TypedAny>({
        url: props.uiForm.api,
        method: 'get',
        params: {
          id: modelValue.value
        }
      })
      formParams.value = data || {}
    }

    // 格式化参数
    onFormatParams()

    // 表单默认下拉
    onInitDefaultData(unref(uiFormItems))

    // 通知结束
    // if (modelValue.value && props.ready) props.ready()

    loading.value = false
  } catch (e) {
    loading.value = false
  }
}

/**
 * 默认的提交验证
 */
const submitForm = async (): Promise<any> => {
  const form = unref(ruleFormRef)
  if (!form) return Promise.resolve(false)
  return new Promise((resolve, reject) => {
    form?.validate((valid) => {
      if (valid) {
        // emitter.emit('onTemplateGridSave')
        onSubmitData().then(resolve).catch(reject)
      } else {
        reject(false)
      }
    })
  })
}

/**
 * 单个批量上传（为了保留idx排序）
 * @param list
 * @param key
 */
const handleBatchUpload = async (list: BusinessUIFile[], key: string) => {
  const result: BusinessUIFile[] = []
  for (let i = 0; i < list.length; i++) {
    let res
    if (key === 'custom-image') {
      res = await UploadBaseImage(list[i])
    } else {
      res = await UploadBaseFile(list[i])
    }
    if (res.data.length) {
      res.data[0].idx = list[i].idx
      result.push(res.data[0])
    }
  }
  return result
}

/**
 * 上传附件或者图片
 * @param dataParams
 * @param key
 */
const handleUpload = async (dataParams: TypedAny, key: string = 'custom-annex') => {
  const items = props.uiForm?.items || []
  const itemComponent = items.find((f) => f.component === key)
  if (itemComponent) {
    const files: BusinessUIFile[] = dataParams[itemComponent.field] || []
    files.forEach((v, idx) => {
      v.idx = idx
    })
    const newFiles = files.filter((f) => f.raw)
    const oldFiles = files.filter((f) => !f.raw)
    if (newFiles.length) {
      const result = await handleBatchUpload(newFiles, key)
      dataParams[itemComponent.field] = oldFiles.concat(result)
    } else {
      dataParams[itemComponent.field] = files
    }
  }
}

/**
 * 提交数据
 */
const onSubmitData = async () => {
  if (!props.uiForm) return Promise.reject(false)
  config.url = props.uiForm?.api || ''
  const dataParams: any = clone(unref(formParams), true)

  // 上传附件
  await handleUpload(dataParams, 'custom-annex')

  // 上传图片
  await handleUpload(dataParams, 'custom-image')

  if (config.url) {
    config.data = Object.assign(dataParams, props.params)
    loading.value = true
    return CustomRequest(config).finally(() => (loading.value = false))
  } else {
    loading.value = false
    ElMessage.warning('还未配置接口信息')
    return false
  }
}

/**
 * 更新格式化数据
 */
const onFormatParams = () => {
  formatParams.value = clone(unref(formParams), true)
  formatColumnRows([unref(formatParams)], unref(dicItems), props.uiTable, props.uiForm)
}

/**
 * 子表传递回来的数据
 */
const onUpdateParent = (data: UpdateParentType) => {
  const item = data.forms.find((f) => f.id === formParams.value.id)
  if (item) {
    if (item.update && isObject(item.update)) {
      for (const k in item.update) {
        const d = uiFormItems.value.find((f) => f.field === k)
        if (d) {
          if (d.type === 'number') {
            formParams.value[k] = Number(item.update[k]) || 0
          } else {
            formParams.value[k] = item.update[k]
          }
        } else {
          formParams.value[k] = item.update[k]
        }
      }
      onFormatParams()
    } else {
      onFetch()
    }
  }
}

/**
 * 每次查询栏配置变化进行初始化
 */
const initDefaultData = () => {
  if (!props.uiForm) return

  // 重置及获取默认值
  onResetParams()
  // 拿字典
  onFetchDictionary()
  // 重置验证
  clearValidate()
}

const clearValidate = () => {
  nextTick(() => {
    const $form = unref(ruleFormRef)
    if ($form) $form.clearValidate()
  })
}

watch(
  () => props.uiForm?.id,
  (id) => {
    if (id && props.uiForm) {
      formLabelPosition.value = props.uiForm.align || 'top'
      // 每次配置变化进行初始化
      initDefaultData()
    }
  },
  { immediate: true }
)

watch(modelValue, (value) => {
  if (value) clearValidate()
})

onBeforeMount(() => {
  emitter.on('onUpdateParent', onUpdateParent)
})

onUnmounted(() => {
  emitter.off('onUpdateParent')
})

defineExpose({ submitForm, onFetch })
</script>

<template>
  <TemplateFormBox
    v-if="isForm"
    ref="ruleFormRef"
    v-model="formParams"
    :format-params="formatParams"
    :get-options="getOptions"
    :items="formItems"
    :params="params"
    :label-position="labelPosition || formLabelPosition"
    :can_edit_items="can_edit_items"
    @linkage="onLinkageChange"
  />
  <TemplateFormDetail
    v-else
    ref="ruleFormRef"
    v-model="formParams"
    :params="params"
    :format-params="formatParams"
    :items="formItems"
  />
</template>
